package com.epalmpay.service.activity.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import com.epalmpay.entity.*;
import com.epalmpay.enumdef.ActivityEnum;
import com.epalmpay.enumdef.CommonEnum;
import com.epalmpay.mapper.*;
import com.epalmpay.service.thread.CheckCouponActivityRuleThread;
import com.epalmpay.util.DateUtil;
import com.epalmpay.util.Logger;
import com.epalmpay.util.StringUtil;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;

import com.epalmpay.service.activity.ICouponUserService;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

@Service("couponUserService")
public class CouponUserServiceImpl implements ICouponUserService{
	protected Logger logger = Logger.getLogger(this.getClass());

	@Resource
	private CouponUserMapper couponUserMapper;

	@Resource
	CouponMapper couponMapper;

	@Resource(name="transactionManager")
	private DataSourceTransactionManager transactionManager;
	@Resource
	private ActivityUnroutineRuleMapper activityUnroutineRuleMapper;
	@Resource
	private ActivityBaseMapper activityBaseMapper;


	/***
	 * 给单个会员发优惠券(手动事物)
	 * @param memberId
	 * @param
	 * @param activityId
	 * @param getType
	 * @param memo
	 * @return
	 *     -1:优惠券已经结束
	 *     -2:优惠券已经领取完成
	 *     -3:优惠券已经过期
	 *     -4:过了有效结束时间
	 *     -5:超过最大领取张数
	 *     1:成功
	 * @throws Exception
	 */
	public int sendOneMemberCoupon(Long memberId,Long couponId,Long activityId,Integer getType,String memo, Long relatedTradeOfflineId) throws Exception{
		//DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		//def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事物隔离级别，开启新事务
		//TransactionStatus status = transactionManager.getTransaction(def); // 获得事务状态

		Coupon coupon = couponMapper.selectByPrimaryKey(couponId);
		StringBuffer sb = new StringBuffer();
		Coupon couponUpdate = new Coupon();
		couponUpdate.setId(coupon.getId());

		if( coupon.getStatus()== ActivityEnum.CouponStatus.Over.getType()) {
			logger.info(sb.append("优惠券状态:").append(ActivityEnum.CouponStatus.Over.getName()));
			//transactionManager.rollback(status);
			//throw new ApplicationException("优惠券已经结束");
			return -1;
		}
		if( coupon.getStatus()== ActivityEnum.CouponStatus.FinishedGet.getType()) {
			logger.info(sb.append("优惠券状态:").append(ActivityEnum.CouponStatus.FinishedGet.getName()));
			//transactionManager.rollback(status);
			//throw new ApplicationException("优惠券已经领取完成");


			//判断如果领完，需要把状态给设置为已领完
//			if (coupon.getTotalCount() != 0 && (coupon.getTotalCount() - coupon.getHavegetCount() == 0)){
//				couponMapper.updateStatusByCouponId(coupon.getId(), )
//			}



			return -2;
		}
		if( coupon.getStatus()== ActivityEnum.CouponStatus.Expire.getType()) {
			logger.info(sb.append("优惠券状态:").append(ActivityEnum.CouponStatus.Expire.getName()));
			//transactionManager.rollback(status);
			//throw new ApplicationException("优惠券已经过期");
			return -3;
		}
		if(coupon.getValidTimeType()==1){

			String beginTime = DateUtil.fomatDate(new Date(), DateUtil.sdfDay);
			String  endTime = DateUtil.fomatDate(coupon.getValidEndTime(), DateUtil.sdfDay);
			SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
			Date bt = sdf.parse(beginTime);
			Date et=sdf.parse(endTime);
			if(coupon.getValidTimeType() == ActivityEnum.CouponValidType.FixedTime.getType() && (bt).compareTo(et)>0){
				logger.info(sb.append("红包ID:").append(couponId).append("过了有效结束时间!"));
				//transactionManager.rollback(status);
				return -4;
			}
		}else{

			if(coupon.getValidTimeType() == ActivityEnum.CouponValidType.FixedTime.getType() && (new Date()).compareTo(coupon.getValidEndTime())>0){
				logger.info(sb.append("红包ID:").append(couponId).append("过了有效结束时间!"));
				//transactionManager.rollback(status);
				return -4;
			}
		}
		//检查最大数量(除了不限的情况)
		int count = couponUserMapper.selectSendCouponCount(memberId,couponId);
		coupon.setAmountPeruser(coupon.getAmountPeruser()==null?0:coupon.getAmountPeruser());
		if( count >= coupon.getAmountPeruser() && coupon.getAmountPeruser() != -1) {
			logger.info(sb.append("超过最大领取张数"));
			//transactionManager.rollback(status);
			//throw new ApplicationException("优惠券超过最大领取张数");
			return -5;
		}

		try {
			//couponUpdate.setTotalCount(couponUpdate.getTotalCount()==null?0:couponUpdate.getTotalCount());
			couponUpdate.setSendCount(coupon.getSendCount() == null ? 0 : coupon.getSendCount());
			couponUpdate.setHavegetCount(coupon.getHavegetCount() == null ? 0 : coupon.getHavegetCount());
			couponUpdate.setGmtModified(new Date());
			if(coupon.getReceiveGroupid()!=null){
				//表示异业联盟
				couponUpdate.setSendCount(couponUpdate.getSendCount() + 1);
			}
			couponUpdate.setHavegetCount(couponUpdate.getHavegetCount() + 1);

			if(coupon.getTotalCount() != 0 && coupon.getAmountPeruser() != -1) {//如果限量
				if (couponUpdate.getHavegetCount().equals(coupon.getTotalCount())) {
					couponUpdate.setStatus(ActivityEnum.CouponStatus.FinishedGet.getType());

					//如果是动态活动优惠券或者异业优惠券则检查是否有活动规则使用到这个优惠券并且删除活动规则或者结束活动
					if (coupon.getPurposeType().equals(ActivityEnum.PurposeType.UnRoutine.getType()) ||
							coupon.getPurposeType().equals(ActivityEnum.PurposeType.otherCoupon.getType())) {
						logger.debug(">>>>>>优惠券已发完，开始异步检查使用本优惠券的动态活动<<<<<<");
						new Thread(new CheckCouponActivityRuleThread(couponId.toString(), activityUnroutineRuleMapper, activityBaseMapper)).start();
					}
				}
			}
			
			couponMapper.updateByPrimaryKeySelective(couponUpdate);
			if(coupon.getReceiveGroupid()==null){
				//插入会员优惠券表
				CouponUser couponUser = new CouponUser();
				couponUser.setGmtCreate(new Date());
				couponUser.setGmtModified(new Date());
				couponUser.setGetTime(new Date());//领取时间
				//取有效期
				Date validTime = null;
				Date validStartTime = null;
				if (coupon.getValidTimeType() == ActivityEnum.CouponValidType.FixedTime.getType()) {
					validStartTime = coupon.getValidStartTime();
					validTime = coupon.getValidEndTime();
				} else if (coupon.getValidTimeType() == ActivityEnum.CouponValidType.ValidAfterGet.getType()) {
					validStartTime = new Date();
					validTime = DateUtil.getAfterDay(coupon.getDays());
				}
				couponUser.setValidStartTime(validStartTime);
				couponUser.setValidTime(validTime);
				couponUser.setMemberId(memberId);
				couponUser.setCouponCode((new StringBuffer()).append("CP").append(DateUtil.fomatDate(new Date(), DateUtil.sdfMonthDay))
						.append(String.format("%06d", memberId)).append(StringUtil.getRandNumberStr(10000, 99999)).toString());//优惠券码生成规则
				couponUser.setCouponId(couponId);
				couponUser.setCouponUseStatus(ActivityEnum.CouponUseStatus.Received.getType());
				couponUser.setActivityId(activityId);
				couponUser.setGetType(getType);
				couponUser.setGroupId(coupon.getGroupId());
				couponUser.setRemark(memo);
				couponUser.setTradeOfflineId(relatedTradeOfflineId);
				couponUserMapper.insert(couponUser);
				
			}else{
				 CouponUser couponUser =couponUserMapper.selectByCouponIdAndStatus(coupon.getId(),ActivityEnum.CouponUseStatus.UnReceive.getType());
				 couponUser.setGetTime(new Date());//领取时间
					//取有效期
					Date validTime = null;
					Date validStartTime = null;
					if (coupon.getValidTimeType() == ActivityEnum.CouponValidType.FixedTime.getType()) {
						validStartTime = coupon.getValidStartTime();
						validTime = coupon.getValidEndTime();
					} else if (coupon.getValidTimeType() == ActivityEnum.CouponValidType.ValidAfterGet.getType()) {
						validStartTime = new Date();
						validTime = DateUtil.getAfterDay(coupon.getDays());
					}
					couponUser.setValidStartTime(validStartTime);
					couponUser.setValidTime(validTime);
					couponUser.setMemberId(memberId);
					couponUser.setCouponUseStatus(ActivityEnum.CouponUseStatus.Received.getType());
					couponUser.setActivityId(activityId);
					couponUser.setGetType(getType);		
					couponUser.setRemark(memo);
					couponUser.setTradeOfflineId(relatedTradeOfflineId);
	             int result = couponUserMapper.updateByPrimaryKeySelective(couponUser);
			}
			//transactionManager.commit(status);
		}catch (Exception e) {
			//transactionManager.rollback(status);
			logger.error("commit", e);
			//throw new ApplicationException("500", "commit transaction exception");
			e.printStackTrace();
			throw e;
		}
		return 1;
	}

	public int sendOneMemberCoupon(Long memberId,Long couponId,Long activityId,Integer getType, Long relatedTradeOfflineId) throws Exception{
		return sendOneMemberCoupon(memberId,couponId,activityId,getType,null, relatedTradeOfflineId);
	}

	/*
	*  根据交易金额、商品获取当前会员可用的优惠券
	*  这个方法只能用于查询，在提交订单时如果要锁定优惠券应该将查询和锁定放在同一个SQL语句中
	*  前两个参数为必传，另外三个可为空
	*/
	@Override
	public List<Map<String, Object>> listUserCouponsInfo(Long memberId, Long goodOrShopId, Integer tradeMoney,
												  ActivityEnum.ActivityPlatformType activityPlatformType, CommonEnum.GoodType goodType) throws ParseException {

		Date now = new Date();

		List<Map<String, Object>> userCoupons = couponUserMapper.listUserCouponsInfo(memberId, ActivityEnum.CouponUseStatus.Received.getType(),
				tradeMoney, activityPlatformType.getType(), goodType.getType());

		if (userCoupons != null && userCoupons.size() > 0) {
			Iterator<Map<String, Object>> couponIterator = userCoupons.iterator();
			while (couponIterator.hasNext()) {
				Map<String, Object> coupon = couponIterator.next();

				//优惠券是否在有效期
				if ((Integer) coupon.get("validTimeType") == ActivityEnum.ValidTimeType.FixedTime.getType()) {
					String beginTime = DateUtil.fomatDate(new Date(), DateUtil.sdfDay);
					String  startTime = DateUtil.fomatDate((Date)coupon.get("validStartTime"), DateUtil.sdfDay);
					String  endTime = DateUtil.fomatDate((Date)coupon.get("validEndTime"), DateUtil.sdfDay);
					SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
					Date bt = sdf.parse(beginTime);
					Date st=sdf.parse(startTime);
					Date et=sdf.parse(endTime);

					if (bt.compareTo(st) < 0 || bt.compareTo(et) > 0) {
						couponIterator.remove();
						continue;
					}
/*
					if (now.compareTo((Date) coupon.get("validStartTime")) < 0 || now.compareTo((Date) coupon.get("validEndTime")) > 0) {
						couponIterator.remove();
						continue;
					}
*/
				} else if ((Integer) coupon.get("validTimeType") == ActivityEnum .ValidTimeType.AfterGet.getType()) {
					Integer days = (Integer) coupon.get("days");
					Date validUseEnd = DateUtil.getDateNext((Date) coupon.get("getTime"), days);
					if (now.compareTo(validUseEnd) > 0) {
						couponIterator.remove();
						continue;
					}

//					Integer days = (Integer) coupon.get("days");
//					String beginTime = DateUtil.fomatDate(new Date(), DateUtil.sdfDay);
//					String  endTime = DateUtil.fomatDate(DateUtil.getDateNext((Date) coupon.get("getTime"), days), DateUtil.sdfDay);
//					SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
//					Date bt = sdf.parse(beginTime);
//					Date et=sdf.parse(endTime);
//					if (bt.compareTo(et) > 0) {
//						couponIterator.remove();
//						continue;
//					}

				} else { //其他有效日期类型无效
					couponIterator.remove();
					continue;
				}

				//优惠券是否可用
				String shopIdsStr = (String) coupon.get("shopIds");
				String[] shopIds;
				if (shopIdsStr == null || shopIdsStr.equals("-1")) {    //所有商品可用
					continue;
				} else {
					shopIds = shopIdsStr.split(",");
				}

				boolean contains = false;
				for (int j = 0; j < shopIds.length; j++) {
					if (Long.parseLong(shopIds[j]) == goodOrShopId) {
						contains = true;
						break;
					}
				}
				if (!contains) {
					couponIterator.remove();
				}
				coupon.remove("shopIds");   //移除门店信息
			}
		}
		return userCoupons;
	}

	
	

}
